using System;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;

using Pegasus.ServiceProcess;
using Pegasus.Log4Net;

namespace Pegasus.Sample.ServiceDebugging
{
	/// <summary>
	/// This is the sample service.
	/// </summary>
	/// <remarks>
	/// Replace the ServiceBase base class with the Pegasus ServiceExecutable class.
	/// </remarks>
	public partial class SampleService : ServiceExecutable
	{
		// Local Const Values
		private ILog m_log = LogManager.GetLogger( typeof( SampleService ) );
		private Thread m_serviceThread;
		private AutoResetEvent m_done = new AutoResetEvent( false );
		private ManualResetEvent m_running = new ManualResetEvent( true );

		// Public Const Values
		public const string SERVICE_NAME = "PegasusSample";
		public const string SERVICE_DISPLAY_NAME = "Pegasus Sample Service";
		public const string SERVICE_DESCRIPTION = "Pegasus Sample Service";

		/// <summary>
		/// Initializes a new instance of the <see cref="SampleService"/> class.
		/// </summary>
		public SampleService()
			: base( SERVICE_NAME )
		{
			InitializeComponent();

			// Set system capibilites.
			CanPauseAndContinue = true;
			CanShutdown = true;

			// Set the installer type for this service
			ServiceInstallerType = typeof( SampleServicetInstaller );
		}

		/// <summary>
		/// When implemented in a derived class, executes when a Start command is sent to the service by the Service 
		/// Control Manager (SCM) or when the operating system starts (for a service that starts automatically). 
		/// Specifies actions to take when the service starts.
		/// </summary>
		/// <param name="args">Data passed by the start command.</param>
		protected override void OnStart( string[] args )
		{
			// There is where you start your service
			
			// For this example we will just run a simple background thread that 
			// writes a debug message every second.
			m_serviceThread = new Thread( new ThreadStart( ThreadProcess ) );
			m_serviceThread.Start();
		}

		/// <summary>
		/// Called when the service should pause.
		/// </summary>
		protected override void OnPause()
		{
			m_log.Info( "Service is pausing." );
			if( m_serviceThread != null )
			{
				m_running.Reset();
			}
		}

		/// <summary>
		/// Called when the service should continue.
		/// </summary>
		protected override void OnContinue()
		{
			m_log.Info( "Service is resuming." );
			if( m_serviceThread != null )
			{
				m_running.Set();
			}
		}

		/// <summary>
		/// When implemented in a derived class, executes when a Stop command is sent to the service by the Service 
		/// Control Manager (SCM). Specifies actions to take when a service stops running.
		/// </summary>
		protected override void OnStop()
		{
			m_log.Info( "Service is stopping." );

			if( m_serviceThread != null )
			{
				// If the service was paused then resume the service.
				if( !m_running.WaitOne( 0, false ) )
				{
					OnContinue();
				}

				m_done.Set();
				m_serviceThread.Join();
				m_serviceThread = null;
			}
		}

		/// <summary>
		/// Called when the service is stopping because of a system shutdown.
		/// </summary>
		protected override void OnShutdown()
		{
			m_log.Info( "Service is stopping, because of a system shutdown." );
			OnStop();
		}

		/// <summary>
		/// The background thread.
		/// </summary>
		private void ThreadProcess()
		{
			while( !m_done.WaitOne( 1000, false ) )
			{
				if( m_running.WaitOne( 0, false ) )
				{
					// Log4Net logging methods.
					m_log.Debug( "This is the debug message" );
					m_log.Info( "This is the info message" );
					m_log.Warn( "This is the warn message" );
					m_log.Error( "This is the error message" );
					m_log.Fatal( "This is the fatal message" );

					// Standard .NET tracing methods.
					Debug.WriteLine( "This is .NET Debug" );
					Trace.WriteLine( "This is .NET Trace" );
				}
				else
				{
					// Wait to be signalled
					m_running.WaitOne();
				}
			}
		}
	}
}
